from django.shortcuts import render
from rest_framework.decorators import api_view, permission_classes
from rest_framework.response import Response
from rest_framework import status
from django.core.paginator import Paginator
from .models import Bill
from users.models import User, Company, ParkEmployeeProfile, CompanyEmployeeProfile
from services.models import Contract, LeasingApplicationService, ParkingSpaceLeasingService, RepairService, CleaningBookingService, WaterDeliveryService
from assets.models import Unit
from rest_framework.permissions import IsAuthenticated
from datetime import datetime, timedelta
from django.utils import timezone
import uuid
import logging
from django.db.models import Q
from django.conf import settings
import os
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import cm
import json

# 获取日志记录器
logger = logging.getLogger(__name__)

# Create your views here.

def _get_user_real_name(user: User):
    """
    获取用户的真实姓名，如果档案不存在则返回其用户名。
    """
    if not user:
        return None
    # 尝试从企业员工档案获取
    profile = CompanyEmployeeProfile.objects.filter(user=user).first()
    if profile:
        return profile.name
    # 其次从园区员工档案获取
    profile = ParkEmployeeProfile.objects.filter(user=user).first()
    if profile:
        return profile.name
    # 如果都没有，返回用户名
    return user.username

@api_view(['POST'])
@permission_classes([IsAuthenticated])
def generate_contract_attachment(request, contract_id):
    """
    为指定合同生成PDF附件的API视图
    """
    try:
        attachment_url = generate_contract_attachment_logic(contract_id)
        
        return Response({
            'code': 200,
            'message': '合同附件生成成功',
            'data': {
                'attachment_url': attachment_url
            }
        })
        
    except Contract.DoesNotExist:
        return Response({
            'code': 404,
            'message': '合同不存在'
        }, status=status.HTTP_404_NOT_FOUND)
    except Exception as e:
        logger.error(f"生成合同附件失败: {str(e)}", exc_info=True)
        return Response({
            'code': 500,
            'message': f'生成合同附件失败: {str(e)}'
        }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

def generate_contract_attachment_logic(contract_id):
    """
    为指定合同生成PDF附件的核心逻辑
    """
    # 获取合同信息
    contract = Contract.objects.select_related(
        'company', 'user', 'unit', 'vehicle'
    ).get(pk=contract_id)
    
    # 创建合同保存目录
    contract_dir = os.path.join(settings.BASE_DIR, '..', 'front', 'web-smartpark', 'public', 'contracts')
    os.makedirs(contract_dir, exist_ok=True)
    
    # 生成文件名和路径
    file_name = f"contract_{contract.contract_number}.pdf"
    file_path = os.path.join(contract_dir, file_name)
    
    # 生成PDF
    generate_contract_pdf(contract, file_path)
    
    # 更新合同的attachment_urls字段
    relative_path = f"/contracts/{file_name}"
    
    # 如果已有附件，则添加到列表中
    if contract.attachment_urls:
        try:
            attachments = json.loads(contract.attachment_urls)
            if isinstance(attachments, list):
                attachments.append(relative_path)
            else:
                attachments = [relative_path]
        except json.JSONDecodeError:
            attachments = [relative_path]
    else:
        attachments = [relative_path]
    
    contract.attachment_urls = json.dumps(attachments)
    contract.save()
    
    return relative_path

def generate_contract_pdf(contract, file_path):
    """
    生成合同PDF文件
    """
    # 创建画布
    c = canvas.Canvas(file_path, pagesize=A4)
    width, height = A4
    
    # 尝试注册中文字体
    try:
        # 查找系统中的中文字体
        font_paths = [
            # Windows中文字体路径
            "C:/Windows/Fonts/simhei.ttf",  # 黑体
            "C:/Windows/Fonts/simsun.ttc",  # 宋体
            "C:/Windows/Fonts/simkai.ttf",  # 楷体
            # Linux中文字体路径
            "/usr/share/fonts/truetype/wqy/wqy-microhei.ttc",
            "/usr/share/fonts/truetype/arphic/uming.ttc",
            # macOS中文字体路径
            "/System/Library/Fonts/PingFang.ttc",
            "/Library/Fonts/Arial Unicode.ttf"
        ]
        
        font_found = False
        for font_path in font_paths:
            if os.path.exists(font_path):
                from reportlab.pdfbase import pdfmetrics
                from reportlab.pdfbase.ttfonts import TTFont
                
                # 注册字体
                if "simsun.ttc" in font_path:
                    pdfmetrics.registerFont(TTFont('SimSun', font_path, subfontIndex=0))
                    font_name = 'SimSun'
                elif "simhei.ttf" in font_path:
                    pdfmetrics.registerFont(TTFont('SimHei', font_path))
                    font_name = 'SimHei'
                else:
                    # 为其他字体生成一个通用名称
                    font_base_name = os.path.basename(font_path).split('.')[0]
                    pdfmetrics.registerFont(TTFont(font_base_name, font_path))
                    font_name = font_base_name
                
                font_found = True
                logger.info(f"成功注册中文字体: {font_name} 从 {font_path}")
                break
        
        if not font_found:
            # 如果没有找到中文字体，使用默认字体
            logger.warning("未找到中文字体，将使用默认字体，中文可能显示为乱码")
            font_name = 'Helvetica'
    except Exception as e:
        logger.error(f"注册中文字体失败: {str(e)}")
        font_name = 'Helvetica'
    
    # 辅助函数：绘制下划线
    def draw_underline(x, y, width, text=""):
        c.setDash(1, 0)  # 实线
        c.line(x, y, x + width, y)
        if text:
            c.drawString(x, y + 2, text)
    
    # 绘制页眉
    c.setFont(font_name, 18)
    c.drawCentredString(width/2, height - 2*cm, "租赁合同")
    
    # 绘制合同编号
    c.setFont(font_name, 10)
    c.drawString(width - 7*cm, height - 3*cm, f"合同编号：{contract.contract_number}")
    
    # 合同正文起始位置
    y_position = height - 4*cm
    
    # 绘制甲乙双方信息
    c.setFont(font_name, 12)
    c.drawString(2*cm, y_position, "甲方（出租方）：")
    draw_underline(6*cm, y_position, 10*cm, contract.party_b)
    
    y_position -= 1*cm
    c.drawString(2*cm, y_position, "乙方（承租方）：")
    if contract.company:
        draw_underline(6*cm, y_position, 10*cm, contract.company.company_name)
    elif contract.user:
        user_name = _get_user_real_name(contract.user)
        draw_underline(6*cm, y_position, 10*cm, user_name)
    
    # 合同正文
    y_position -= 1.5*cm
    c.setFont(font_name, 11)
    c.drawString(2*cm, y_position, "根据《中华人民共和国民法典》及有关法律、法规的规定，甲乙双方在平等、自愿、协商一致的基础上，就")
    y_position -= 0.6*cm
    c.drawString(2*cm, y_position, "租赁事宜达成如下协议：")
    
    # 第一条
    y_position -= 1*cm
    c.setFont(font_name, 11)
    c.drawString(2*cm, y_position, "第一条 租赁标的物")
    
    y_position -= 0.8*cm
    c.setFont(font_name, 10)
    if contract.contract_type == '房源租赁' and contract.unit:
        building_name = contract.unit.building.name if hasattr(contract.unit, 'building') and contract.unit.building else "未知楼宇"
        floor_label = contract.unit.floor.actual_label if hasattr(contract.unit, 'floor') and contract.unit.floor else "未知楼层"
        unit_number = contract.unit.unit_number
        c.drawString(2*cm, y_position, f"1.1 甲方将位于")
        draw_underline(5*cm, y_position, 3*cm, building_name)
        c.drawString(8.5*cm, y_position, "楼")
        draw_underline(9.5*cm, y_position, 2*cm, floor_label)
        c.drawString(12*cm, y_position, "层")
        draw_underline(13*cm, y_position, 3*cm, unit_number)
        c.drawString(16.5*cm, y_position, "号的房屋出租给乙方使用。")
        
        y_position -= 0.8*cm
        area = str(contract.unit.actual_area) if contract.unit.actual_area else "____"
        c.drawString(2*cm, y_position, f"1.2 该房屋建筑面积为")
        draw_underline(6*cm, y_position, 3*cm, area)
        c.drawString(9.5*cm, y_position, "平方米。")
    elif contract.contract_type == '车位租赁' and contract.unit and contract.vehicle:
        c.drawString(2*cm, y_position, f"1.1 甲方将位于")
        building_name = contract.unit.building.name if hasattr(contract.unit, 'building') and contract.unit.building else "未知楼宇"
        draw_underline(5*cm, y_position, 3*cm, building_name)
        c.drawString(8.5*cm, y_position, "停车场")
        draw_underline(11*cm, y_position, 3*cm, contract.unit.unit_number)
        c.drawString(14.5*cm, y_position, "号车位出租给乙方使用。")
        
        y_position -= 0.8*cm
        c.drawString(2*cm, y_position, f"1.2 该车位对应乙方车辆信息为：车牌号")
        draw_underline(10*cm, y_position, 3*cm, contract.vehicle.plate_number)
        
        y_position -= 0.8*cm
        c.drawString(2*cm, y_position, f"    车辆品牌型号：")
        brand_model = f"{contract.vehicle.brand} {contract.vehicle.model}" if contract.vehicle.brand and contract.vehicle.model else "____"
        draw_underline(6*cm, y_position, 8*cm, brand_model)
    
    # 第二条
    y_position -= 1.2*cm
    c.setFont(font_name, 11)
    c.drawString(2*cm, y_position, "第二条 租赁期限")
    
    y_position -= 0.8*cm
    c.setFont(font_name, 10)
    start_date = contract.start_date.strftime('%Y年%m月%d日')
    end_date = contract.end_date.strftime('%Y年%m月%d日')
    c.drawString(2*cm, y_position, f"2.1 租赁期限自")
    draw_underline(5*cm, y_position, 4*cm, start_date)
    c.drawString(9.5*cm, y_position, "起至")
    draw_underline(11*cm, y_position, 4*cm, end_date)
    c.drawString(15.5*cm, y_position, "止。")
    
    # 第三条
    y_position -= 1.2*cm
    c.setFont(font_name, 11)
    c.drawString(2*cm, y_position, "第三条 租金及支付方式")
    
    y_position -= 0.8*cm
    c.setFont(font_name, 10)
    contract_amount = str(contract.contract_amount)
    c.drawString(2*cm, y_position, f"3.1 租赁期内租金总额为人民币")
    draw_underline(8*cm, y_position, 3*cm, contract_amount)
    c.drawString(11.5*cm, y_position, "元整。")
    
    y_position -= 0.8*cm
    c.drawString(2*cm, y_position, f"3.2 支付方式：")
    draw_underline(5*cm, y_position, 3*cm, contract.payment_cycle)
    
    # 第四条
    y_position -= 1.2*cm
    c.setFont(font_name, 11)
    c.drawString(2*cm, y_position, "第四条 甲方权利与义务")
    
    y_position -= 0.8*cm
    c.setFont(font_name, 10)
    c.drawString(2*cm, y_position, "4.1 甲方应保证租赁物业的使用安全。")
    
    y_position -= 0.8*cm
    c.drawString(2*cm, y_position, "4.2 甲方有权依约收取租金。")
    
    # 第五条
    y_position -= 1.2*cm
    c.setFont(font_name, 11)
    c.drawString(2*cm, y_position, "第五条 乙方权利与义务")
    
    y_position -= 0.8*cm
    c.setFont(font_name, 10)
    c.drawString(2*cm, y_position, "5.1 乙方应按时支付租金。")
    
    y_position -= 0.8*cm
    c.drawString(2*cm, y_position, "5.2 乙方应合理使用租赁物业，不得擅自改变其用途。")
    
    # 第六条
    y_position -= 1.2*cm
    c.setFont(font_name, 11)
    c.drawString(2*cm, y_position, "第六条 合同解除")
    
    y_position -= 0.8*cm
    c.setFont(font_name, 10)
    c.drawString(2*cm, y_position, "6.1 经双方协商一致，可以解除本合同。")
    
    y_position -= 0.8*cm
    c.drawString(2*cm, y_position, "6.2 任何一方违约，守约方有权解除合同并要求违约方赔偿损失。")
    
    # 第七条
    y_position -= 1.2*cm
    c.setFont(font_name, 11)
    c.drawString(2*cm, y_position, "第七条 其他约定")
    
    y_position -= 0.8*cm
    c.setFont(font_name, 10)
    c.drawString(2*cm, y_position, "7.1 本合同一式两份，甲乙双方各执一份，具有同等法律效力。")
    
    y_position -= 0.8*cm
    c.drawString(2*cm, y_position, "7.2 本合同未尽事宜，由甲乙双方另行协商并签订补充协议。")
    
    y_position -= 0.8*cm
    c.drawString(2*cm, y_position, "7.3 本合同自双方签字盖章之日起生效。")
    
    # 签名区域
    y_position -= 1.5*cm
    c.setFont(font_name, 11)
    c.drawString(2*cm, y_position, "甲方（签章）：")
    c.drawString(width/2 + 1*cm, y_position, "乙方（签章）：")
    
    # 签名下划线
    y_position -= 1*cm
    draw_underline(2*cm, y_position, 6*cm)
    draw_underline(width/2 + 1*cm, y_position, 6*cm)
    
    # 日期
    y_position -= 1.5*cm
    c.drawString(width/2 - 2*cm, y_position, "签订日期：")
    
    # 日期下划线
    y_position -= 0.5*cm
    draw_underline(width/2 - 2*cm, y_position, 4*cm)
    
    # 保存PDF
    c.save()

@api_view(['POST'])
@permission_classes([IsAuthenticated])
def create_contract(request):
    """
    根据租赁申请创建合同
    """
    data = request.data
    application_id = data.get('application_id')
    application_type = data.get('application_type')
    
    logger.info(f"开始创建合同: application_id={application_id}, application_type={application_type}")
    
    if not application_id or not application_type:
        logger.warning(f"缺少必要参数: application_id={application_id}, application_type={application_type}")
        return Response({
            'code': 400,
            'message': '缺少必要参数'
        }, status=status.HTTP_400_BAD_REQUEST)
    
    # 确保application_id是整数
    try:
        # 如果是字符串且包含非数字字符，尝试提取数字部分
        if isinstance(application_id, str) and not application_id.isdigit():
            numeric_id = ''.join(filter(str.isdigit, application_id))
            if numeric_id:
                application_id = int(numeric_id)
            else:
                logger.error(f"无法从application_id中提取数字: {application_id}")
                return Response({
                    'code': 400,
                    'message': '无效的申请ID格式'
                }, status=status.HTTP_400_BAD_REQUEST)
        else:
            application_id = int(application_id)
        
        logger.info(f"处理后的application_id: {application_id}")
    except (ValueError, TypeError) as e:
        logger.error(f"application_id转换为整数失败: {str(e)}")
        return Response({
            'code': 400,
            'message': '无效的申请ID格式'
        }, status=status.HTTP_400_BAD_REQUEST)
    
    try:
        # 生成合同编号
        contract_number = f"CT-{timezone.now().strftime('%Y%m%d')}-{uuid.uuid4().hex[:6].upper()}"
        logger.info(f"生成合同编号: {contract_number}")
        
        # 根据申请类型获取相应的申请记录
        if application_type == '房源租赁':
            try:
                logger.info(f"查询房源租赁申请: id={application_id}")
                application = LeasingApplicationService.objects.select_related(
                    'applicant_user', 'company', 'unit'
                ).get(pk=application_id)
                logger.info(f"找到房源租赁申请: {application}")
            except LeasingApplicationService.DoesNotExist:
                logger.error(f"房源租赁申请不存在: id={application_id}")
                return Response({
                    'code': 404,
                    'message': '房源租赁申请不存在'
                }, status=status.HTTP_404_NOT_FOUND)
            
            # 检查申请状态
            if application.status != '审核通过':
                logger.warning(f"申请状态不是'审核通过': status={application.status}")
                return Response({
                    'code': 400,
                    'message': '只有审核通过的申请才能创建合同'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # 检查必要的关联数据
            if not application.unit:
                logger.error("申请未关联单元")
                return Response({
                    'code': 400,
                    'message': '申请未关联单元'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            if not application.unit.rental_price:
                logger.error("单元未设置租金单价")
                return Response({
                    'code': 400,
                    'message': '单元未设置租金单价'
                }, status=status.HTTP_400_BAD_REQUEST)
                
            if not application.expected_duration:
                logger.error("申请未设置预期租期")
                return Response({
                    'code': 400,
                    'message': '申请未设置预期租期'
                }, status=status.HTTP_400_BAD_REQUEST)
                
            if not application.expected_start_date:
                logger.error("申请未设置预期开始日期")
                return Response({
                    'code': 400,
                    'message': '申请未设置预期开始日期'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            try:
                # 创建合同，确保字段名与数据库表结构匹配
                logger.info("开始创建房源租赁合同")
                current_time = timezone.now()
                
                # 根据新的字段含义:
                # - party_b 字段表示"甲方主体"（出租方/园区）
                # - company_id 字段表示"乙方企业ID"（承租方/企业）
                # - user_id 字段表示"乙方用户ID"（承租方/个人）
                
                contract = Contract(
                    contract_number=contract_number,
                    contract_name=f"{application.unit.unit_number}房源租赁合同",
                    contract_type='房源租赁',
                    company=application.company,  # 乙方是企业（承租方）
                    user=None if application.company else application.applicant_user,  # 如果有企业，则个人用户为空
                    party_b="智慧产业园管理方",  # 甲方是园区管理方
                    unit=application.unit,
                    contract_amount=application.unit.rental_price * application.expected_duration,  # 租金单价 * 租期
                    payment_cycle='月付',  # 默认月付
                    start_date=application.expected_start_date,
                    end_date=application.expected_start_date + timedelta(days=30*application.expected_duration),
                    sign_date=None,  # 签约日期暂为空，等用户确认后填写
                    status='未生效',  # 初始状态为未生效
                    remarks=f"由租赁申请 #{application_id} 自动生成",
                    created_at=current_time,
                    updated_at=current_time
                )
                contract.save()
                logger.info(f"房源租赁合同创建成功: id={contract.contract_id}")
            except Exception as e:
                logger.error(f"创建房源租赁合同失败: {str(e)}")
                raise
            
            try:
                # 更新申请记录，关联合同ID
                application.contract = contract
                application.save()
                logger.info(f"更新申请关联合同成功: application_id={application_id}, contract_id={contract.contract_id}")
            except Exception as e:
                logger.error(f"更新申请关联合同失败: {str(e)}")
                # 如果更新申请失败，删除刚创建的合同
                contract.delete()
                raise
            
        elif application_type == '车位租赁':
            try:
                logger.info(f"查询车位租赁申请: id={application_id}")
                application = ParkingSpaceLeasingService.objects.select_related(
                    'applicant_user', 'unit', 'vehicle'
                ).get(pk=application_id)
                logger.info(f"找到车位租赁申请: {application}")
            except ParkingSpaceLeasingService.DoesNotExist:
                logger.error(f"车位租赁申请不存在: id={application_id}")
                return Response({
                    'code': 404,
                    'message': '车位租赁申请不存在'
                }, status=status.HTTP_404_NOT_FOUND)
            
            # 检查申请状态
            if application.status != '审核通过':
                logger.warning(f"申请状态不是'审核通过': status={application.status}")
                return Response({
                    'code': 400,
                    'message': '只有审核通过的申请才能创建合同'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # 检查必要的关联数据
            if not application.unit:
                logger.error("申请未关联车位单元")
                return Response({
                    'code': 400,
                    'message': '申请未关联车位单元'
                }, status=status.HTTP_400_BAD_REQUEST)
                
            if not application.vehicle:
                logger.error("申请未关联车辆")
                return Response({
                    'code': 400,
                    'message': '申请未关联车辆'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            if not application.unit.rental_price:
                logger.error("车位未设置租金单价")
                return Response({
                    'code': 400,
                    'message': '车位未设置租金单价'
                }, status=status.HTTP_400_BAD_REQUEST)
                
            if not application.expected_duration:
                logger.error("申请未设置预期租期")
                return Response({
                    'code': 400,
                    'message': '申请未设置预期租期'
                }, status=status.HTTP_400_BAD_REQUEST)
                
            if not application.expected_start_date:
                logger.error("申请未设置预期开始日期")
                return Response({
                    'code': 400,
                    'message': '申请未设置预期开始日期'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            try:
                # 创建合同，确保字段名与数据库表结构匹配
                logger.info("开始创建车位租赁合同")
                current_time = timezone.now()
                
                # 根据新的字段含义:
                # - party_b 字段表示"甲方主体"（出租方/园区）
                # - company_id 字段表示"乙方企业ID"（承租方/企业）
                # - user_id 字段表示"乙方用户ID"（承租方/个人）
                
                contract = Contract(
                    contract_number=contract_number,
                    contract_name=f"{application.unit.unit_number}车位租赁合同",
                    contract_type='车位租赁',
                    company=None,  # 车位租赁通常不关联企业
                    user=application.applicant_user,  # 乙方是个人用户
                    party_b="智慧产业园管理方",  # 甲方是园区管理方
                    unit=application.unit,
                    vehicle=application.vehicle,
                    contract_amount=application.unit.rental_price * application.expected_duration,  # 租金单价 * 租期
                    payment_cycle='月付',  # 默认月付
                    start_date=application.expected_start_date,
                    end_date=application.expected_start_date + timedelta(days=30*application.expected_duration),
                    sign_date=None,  # 签约日期暂为空，等用户确认后填写
                    status='未生效',  # 初始状态为未生效
                    remarks=f"由车位租赁申请 #{application_id} 自动生成",
                    created_at=current_time,
                    updated_at=current_time
                )
                contract.save()
                logger.info(f"车位租赁合同创建成功: id={contract.contract_id}")
            except Exception as e:
                logger.error(f"创建车位租赁合同失败: {str(e)}")
                raise
            
            try:
                # 更新申请记录，关联合同ID
                application.contract = contract
                application.save()
                logger.info(f"更新申请关联合同成功: application_id={application_id}, contract_id={contract.contract_id}")
            except Exception as e:
                logger.error(f"更新申请关联合同失败: {str(e)}")
                # 如果更新申请失败，删除刚创建的合同
                contract.delete()
                raise
            
        else:
            logger.warning(f"不支持的申请类型: {application_type}")
            return Response({
                'code': 400,
                'message': '不支持的申请类型'
            }, status=status.HTTP_400_BAD_REQUEST)
        
        logger.info(f"合同创建成功: contract_id={contract.contract_id}, contract_number={contract.contract_number}")
        
        # 自动生成合同附件
        try:
            generate_contract_attachment_logic(contract.contract_id)
            logger.info(f"自动生成合同附件成功: contract_id={contract.contract_id}")
        except Exception as e:
            logger.warning(f"自动生成合同附件失败: {str(e)}")
            # 附件生成失败不影响合同创建
        
        return Response({
            'code': 200,
            'message': '合同创建成功',
            'data': {
                'contract_id': contract.contract_id,
                'contract_number': contract.contract_number
            }
        })
        
    except (LeasingApplicationService.DoesNotExist, ParkingSpaceLeasingService.DoesNotExist) as e:
        logger.error(f"申请记录不存在: {str(e)}")
        return Response({
            'code': 404,
            'message': '申请记录不存在'
        }, status=status.HTTP_404_NOT_FOUND)
    except Exception as e:
        logger.error(f"创建合同失败: {str(e)}", exc_info=True)
        return Response({
            'code': 500,
            'message': f'创建合同失败: {str(e)}'
        }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

@api_view(['GET'])
def bill_list(request):
    """
    获取账单列表
    """
    params = request.query_params
    page = int(params.get('current', 1))
    size = int(params.get('size', 10))
    payment_status = params.get('paymentStatus', '')
    payer_name = params.get('payerName', '')
    bill_type = params.get('billType', '')
    
    queryset = Bill.objects.select_related(
        'payer_user', 
        'payer_company'
    ).order_by('-bill_id')
    
    # 根据支付状态筛选
    if payment_status:
        queryset = queryset.filter(payment_status=payment_status)
    
    # 根据账单类型筛选
    if bill_type:
        queryset = queryset.filter(bill_type=bill_type)
    
    # 根据支付方名称筛选
    if payer_name:
        # 同时从公司和用户中查找匹配的支付方
        company_bills = queryset.filter(payer_company__company_name__icontains=payer_name)
        user_bills = queryset.filter(
            Q(payer_user__username__icontains=payer_name) | 
            Q(payer_user__companyemployeeprofile__name__icontains=payer_name) | 
            Q(payer_user__parkemployeeprofile__name__icontains=payer_name)
        )
        queryset = company_bills | user_bills
    
    paginator = Paginator(queryset, size)
    bills_page = paginator.get_page(page)

    bills = []
    for bill in bills_page:
        payer_name = "未知"
        if bill.payer_company:
            payer_name = bill.payer_company.company_name
        elif bill.payer_user:
            payer_name = _get_user_real_name(bill.payer_user)
        
        bills.append({
            'id': bill.bill_id,
            'billNumber': bill.bill_number,
            'payerName': payer_name,
            'amount': str(bill.amount),
            'dueDate': bill.due_date.strftime('%Y-%m-%d'),
            'billType': bill.bill_type,
            'paymentStatus': bill.payment_status,
        })

    return Response({
        'code': 200,
        'message': '获取账单列表成功',
        'data': {
            'total': paginator.count,
            'list': bills
        }
    })

@api_view(['GET'])
def bill_detail(request, pk):
    """
    获取单个账单详情
    """
    try:
        bill = Bill.objects.select_related(
            'payer_user', 'payer_company', 'contract'
        ).get(pk=pk)
    except Bill.DoesNotExist:
        return Response({'code': 404, 'message': '账单不存在'}, status=status.HTTP_404_NOT_FOUND)

    payer_name = "未知"
    if bill.payer_company:
        payer_name = bill.payer_company.company_name
    elif bill.payer_user:
        payer_name = _get_user_real_name(bill.payer_user)

    data = {
        'id': bill.bill_id,
        'billNumber': bill.bill_number,
        'payerName': payer_name,
        'amount': str(bill.amount),
        'dueDate': bill.due_date.strftime('%Y-%m-%d'),
        'paymentDate': bill.payment_date.strftime('%Y-%m-%d') if bill.payment_date else None,
        'paymentStatus': bill.payment_status,
        'billType': bill.bill_type,
        'billPeriod': bill.bill_period,
        'contractId': bill.contract.contract_id if bill.contract else None,
        'contractNumber': bill.contract.contract_number if bill.contract else None,
        'remarks': bill.remarks,
    }

    return Response({
        'code': 200,
        'message': '获取账单详情成功',
        'data': data
    })

# Dashboard统计接口
@api_view(['GET'])
def bill_monthly_count(request):
    """获取账单总数"""
    count = Bill.objects.count()
    return Response({'count': count})

@api_view(['GET'])
def contract_count(request):
    """获取合同总数"""
    count = Contract.objects.count()
    return Response({'count': count})

@api_view(['POST'])
@permission_classes([IsAuthenticated])
def create_bill(request):
    """
    创建账单，支持从维修服务、保洁服务、送水服务等创建账单
    """
    data = request.data
    service_id = data.get('service_id')
    service_type = data.get('service_type')
    amount = data.get('amount')
    
    logger.info(f"开始创建账单: service_id={service_id}, service_type={service_type}, amount={amount}")
    
    if not service_id or not service_type or amount is None:
        logger.warning(f"缺少必要参数: service_id={service_id}, service_type={service_type}, amount={amount}")
        return Response({
            'code': 400,
            'message': '缺少必要参数'
        }, status=status.HTTP_400_BAD_REQUEST)
    
    try:
        # 确保service_id是整数
        service_id = int(service_id)
        # 确保amount是有效的数字
        amount = float(amount)
    except (ValueError, TypeError) as e:
        logger.error(f"参数类型转换失败: {str(e)}")
        return Response({
            'code': 400,
            'message': '无效的参数格式'
        }, status=status.HTTP_400_BAD_REQUEST)
    
    try:
        # 生成账单编号
        bill_number = f"BILL-{service_type.upper()}-{timezone.now().strftime('%Y%m%d')}-{uuid.uuid4().hex[:6].upper()}"
        
        # 根据服务类型获取相应的服务记录
        if service_type == 'repair':
            try:
                service = RepairService.objects.select_related('applicant_user').get(repair_id=service_id)
                
                # 检查服务状态
                if service.status not in ['已完成', '已评价']:
                    return Response({
                        'code': 400,
                        'message': '只有已完成的维修服务才能创建账单'
                    }, status=status.HTTP_400_BAD_REQUEST)
                
                # 检查是否已经有关联的账单
                if service.bill_id:
                    return Response({
                        'code': 400,
                        'message': '该维修服务已经有关联的账单'
                    }, status=status.HTTP_400_BAD_REQUEST)
                
                # 创建账单
                bill = Bill(
                    bill_number=bill_number,
                    payer_user=service.applicant_user,
                    payer_company=None,  # 维修服务通常是个人支付
                    amount=amount,
                    due_date=timezone.now().date() + timedelta(days=7),  # 设置7天后为付款截止日期
                    payment_status='未支付',
                    bill_type='维修费',
                    bill_period=timezone.now().strftime('%Y-%m'),
                    service_id=service_id,
                    remarks=f"维修服务费用 - ID: {service_id}",
                    created_at=timezone.now(),
                    updated_at=timezone.now()
                )
                bill.save()
                
                # 更新服务记录，关联账单ID
                service.bill_id = bill.bill_id
                service.repair_cost = amount  # 更新维修费用
                service.save()
                
                return Response({
                    'code': 200,
                    'message': '账单创建成功',
                    'data': {
                        'bill_id': bill.bill_id,
                        'bill_number': bill.bill_number
                    }
                })
                
            except RepairService.DoesNotExist:
                logger.error(f"维修服务不存在: id={service_id}")
                return Response({
                    'code': 404,
                    'message': '维修服务不存在'
                }, status=status.HTTP_404_NOT_FOUND)
        
        # 添加保洁服务类型的处理逻辑
        elif service_type == 'cleaning':
            try:
                service = CleaningBookingService.objects.select_related('applicant_user').get(booking_id=service_id)
                
                # 检查服务状态
                if service.status not in ['已完成', '已评价']:
                    return Response({
                        'code': 400,
                        'message': '只有已完成的保洁服务才能创建账单'
                    }, status=status.HTTP_400_BAD_REQUEST)
                
                # 检查是否已经有关联的账单
                if service.bill_id:
                    return Response({
                        'code': 400,
                        'message': '该保洁服务已经有关联的账单'
                    }, status=status.HTTP_400_BAD_REQUEST)
                
                # 创建账单
                bill = Bill(
                    bill_number=bill_number,
                    payer_user=service.applicant_user,
                    payer_company=None,  # 保洁服务通常是个人支付
                    amount=amount,
                    due_date=timezone.now().date() + timedelta(days=7),  # 设置7天后为付款截止日期
                    payment_status='未支付',
                    bill_type='保洁费',
                    bill_period=timezone.now().strftime('%Y-%m'),
                    service_id=service_id,
                    remarks=f"保洁服务费用 - ID: {service_id}",
                    created_at=timezone.now(),
                    updated_at=timezone.now()
                )
                bill.save()
                
                # 更新服务记录，关联账单ID
                service.bill_id = bill.bill_id
                service.service_fee = amount  # 更新服务费用
                service.save()
                
                return Response({
                    'code': 200,
                    'message': '账单创建成功',
                    'data': {
                        'bill_id': bill.bill_id,
                        'bill_number': bill.bill_number
                    }
                })
                
            except CleaningBookingService.DoesNotExist:
                logger.error(f"保洁服务不存在: id={service_id}")
                return Response({
                    'code': 404,
                    'message': '保洁服务不存在'
                }, status=status.HTTP_404_NOT_FOUND)
        
        # 添加送水服务类型的处理逻辑
        elif service_type == 'water':
            try:
                service = WaterDeliveryService.objects.select_related('applicant_user').get(service_id=service_id)
                
                # 检查服务状态
                if service.status not in ['已送达', '已评价']:
                    return Response({
                        'code': 400,
                        'message': '只有已送达的送水服务才能创建账单'
                    }, status=status.HTTP_400_BAD_REQUEST)
                
                # 检查是否已经有关联的账单
                if service.bill_id:
                    return Response({
                        'code': 400,
                        'message': '该送水服务已经有关联的账单'
                    }, status=status.HTTP_400_BAD_REQUEST)
                
                # 创建账单
                bill = Bill(
                    bill_number=bill_number,
                    payer_user=service.applicant_user,
                    payer_company=None,  # 送水服务通常是个人支付
                    amount=amount,
                    due_date=timezone.now().date() + timedelta(days=7),  # 设置7天后为付款截止日期
                    payment_status='未支付',
                    bill_type='送水费',
                    bill_period=timezone.now().strftime('%Y-%m'),
                    service_id=service_id,
                    remarks=f"送水服务费用 - ID: {service_id}",
                    created_at=timezone.now(),
                    updated_at=timezone.now()
                )
                bill.save()
                
                # 更新服务记录，关联账单ID
                service.bill_id = bill.bill_id
                service.save()
                
                return Response({
                    'code': 200,
                    'message': '账单创建成功',
                    'data': {
                        'bill_id': bill.bill_id,
                        'bill_number': bill.bill_number
                    }
                })
                
            except WaterDeliveryService.DoesNotExist:
                logger.error(f"送水服务不存在: id={service_id}")
                return Response({
                    'code': 404,
                    'message': '送水服务不存在'
                }, status=status.HTTP_404_NOT_FOUND)
        
        # 可以根据需要添加其他服务类型的处理逻辑
        else:
            logger.warning(f"不支持的服务类型: {service_type}")
            return Response({
                'code': 400,
                'message': '不支持的服务类型'
            }, status=status.HTTP_400_BAD_REQUEST)
    
    except Exception as e:
        logger.error(f"创建账单失败: {str(e)}", exc_info=True)
        return Response({
            'code': 500,
            'message': f'创建账单失败: {str(e)}'
        }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

@api_view(['POST'])
@permission_classes([IsAuthenticated])
def approve_contract(request, contract_id):
    """
    审核合同
    """
    logger.info(f"收到合同审核请求: contract_id={contract_id}, data={request.data}")
    
    try:
        # 获取合同信息
        contract = Contract.objects.get(pk=contract_id)
        logger.info(f"找到合同: contract_id={contract_id}, status={contract.status}, contract_number={contract.contract_number}")
        
        # 检查合同状态
        if contract.status != '未生效':
            logger.warning(f"合同状态不是'未生效': contract_id={contract_id}, status={contract.status}")
            return Response({
                'code': 400,
                'message': f"只有未生效状态的合同可以审核，当前状态: {contract.status}"
            }, status=status.HTTP_400_BAD_REQUEST)
        
        # 获取请求数据
        data = request.data
        approved = data.get('approved', False)
        comment = data.get('comment', '')
        
        logger.info(f"审核参数: approved={approved}, comment={comment}")
        
        # 更新合同状态
        if approved:
            contract.status = '生效中'
            contract.sign_date = timezone.now().date()  # 设置签约日期为当前日期
            message = '合同审核通过'
        else:
            contract.status = '作废'
            message = '合同已驳回'
        
        # 保存审核意见
        if comment:
            if contract.remarks:
                contract.remarks += f"\n审核意见: {comment}"
            else:
                contract.remarks = f"审核意见: {comment}"
        
        # 保存合同
        try:
            contract.save()
            logger.info(f"合同状态已更新: contract_id={contract_id}, new_status={contract.status}")
        except Exception as e:
            logger.error(f"保存合同失败: {str(e)}", exc_info=True)
            return Response({
                'code': 500,
                'message': f'保存合同失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
        
        # 如果合同生效，可能需要更新相关资源状态
        if approved and contract.unit:
            try:
                # 更新单元状态为已租
                contract.unit.status = '已租'
                contract.unit.save()
                logger.info(f"更新单元状态为已租: unit_id={contract.unit.pk}")
            except Exception as e:
                logger.error(f"更新单元状态失败: {str(e)}", exc_info=True)
                # 不影响主流程，继续执行
        
        logger.info(f"合同审核完成: contract_id={contract_id}, approved={approved}")
        
        return Response({
            'code': 200,
            'message': message
        })
        
    except Contract.DoesNotExist:
        logger.error(f"合同不存在: contract_id={contract_id}")
        return Response({
            'code': 404,
            'message': '合同不存在'
        }, status=status.HTTP_404_NOT_FOUND)
    except Exception as e:
        logger.error(f"合同审核失败: {str(e)}", exc_info=True)
        return Response({
            'code': 500,
            'message': f'合同审核失败: {str(e)}'
        }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

@api_view(['GET'])
@permission_classes([IsAuthenticated])
def user_bills(request):
    """
    获取当前登录用户的账单列表
    """
    user = request.user
    
    # 获取查询参数
    payment_status = request.query_params.get('payment_status', '')
    bill_type = request.query_params.get('bill_type', '')
    
    # 查询当前用户的账单
    queryset = Bill.objects.filter(
        Q(payer_user=user) | 
        Q(payer_company__in=user.company_set.all())
    ).order_by('-due_date')
    
    # 根据支付状态筛选
    if payment_status:
        queryset = queryset.filter(payment_status=payment_status)
    
    # 根据账单类型筛选
    if bill_type:
        queryset = queryset.filter(bill_type=bill_type)
    
    # 计算待支付和已支付总额
    unpaid_total = sum(bill.amount for bill in queryset.filter(payment_status='未支付'))
    paid_total = sum(bill.amount for bill in queryset.filter(payment_status='已支付'))
    
    bills = []
    for bill in queryset:
        bills.append({
            'id': bill.bill_id,
            'bill_number': bill.bill_number,
            'amount': str(bill.amount),
            'due_date': bill.due_date.strftime('%Y-%m-%d'),
            'payment_date': bill.payment_date.strftime('%Y-%m-%d') if bill.payment_date else None,
            'payment_status': bill.payment_status,
            'bill_type': bill.bill_type,
            'bill_period': bill.bill_period,
            'remarks': bill.remarks
        })

    return Response({
        'code': 200,
        'message': '获取用户账单列表成功',
        'data': {
            'bills': bills,
            'summary': {
                'unpaid_total': str(unpaid_total),
                'paid_total': str(paid_total)
            }
        }
    })

@api_view(['POST'])
@permission_classes([IsAuthenticated])
def pay_bill(request, pk):
    """
    支付指定账单
    """
    try:
        bill = Bill.objects.get(pk=pk)
    except Bill.DoesNotExist:
        return Response({
            'code': 404,
            'message': '账单不存在'
        }, status=status.HTTP_404_NOT_FOUND)
    
    # 验证用户是否有权限支付此账单
    user = request.user
    if bill.payer_user != user and not bill.payer_company.company_set.filter(pk=user.id).exists():
        return Response({
            'code': 403,
            'message': '您没有权限支付此账单'
        }, status=status.HTTP_403_FORBIDDEN)
    
    # 检查账单是否已支付
    if bill.payment_status == '已支付':
        return Response({
            'code': 400,
            'message': '此账单已支付'
        }, status=status.HTTP_400_BAD_REQUEST)
    
    # 获取支付方式
    payment_method = request.data.get('payment_method', 'online')
    transaction_id = request.data.get('transaction_id', '')
    
    # 更新账单状态
    bill.payment_status = '已支付'
    bill.payment_date = timezone.now().date()
    bill.remarks = f"{bill.remarks or ''}\n支付方式: {payment_method}, 交易号: {transaction_id}"
    bill.updated_at = timezone.now()
    bill.save()
    
    return Response({
        'code': 200,
        'message': '支付成功',
        'data': {
            'bill_id': bill.bill_id,
            'payment_status': bill.payment_status,
            'payment_date': bill.payment_date.strftime('%Y-%m-%d')
        }
    })
